package eHealth.android.REST;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import eHealth.android.client.Menu;

/**
 * 
 * @author Thomas Rouvinez
 * Date 12.03.2012
 * 
 * source : http://lukencode.com/2010/04/27/calling-web-services-in-android-using-httpclient/
 * except for the sendJSON() method.
 * 
 * Goal : create a rest client capable of dealing with both post and get methods.
 *
 */
public class RestClient {
	
	// ---------------------------------------------------------------
	// Variables.
	// ---------------------------------------------------------------
	
	/**
	 * String to get and set the error messages.
	 */
	private String message;
	
	/**
	 * String to get the answer of the web service.
	 */
	private String response;

	/**
	 * Integer to get the response code of the request.
	 */
	private int responseCode;

	/**
	 * HttpResponse object to store revieved data.
	 */
	private HttpResponse responseHttp;

	// ---------------------------------------------------------------
	// Constructor.
	// ---------------------------------------------------------------
	
	/**
	 * Creates a REST client using an URL as parametter.
	 * @param url
	 */
	public RestClient(String url){}

	// ---------------------------------------------------------------
	// Methods.
	// ---------------------------------------------------------------

	/**
	 * Method to send a JSON login and get server response.
	 * @param json
	 * @param header
	 * @return an Integer used for confirmation of successful login.
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException
	 */
	public int sendLogin(JSONObject json, String header) throws ClientProtocolException, IOException, JSONException{
		int responseJSON = -1;

		// Create new connection.
		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
		HttpConnectionParams.setSoTimeout(httpParams, 10000);
		HttpClient client = new DefaultHttpClient(httpParams);

		// Define request in right method.
		String url = Menu.RESTURILogin;
		HttpPost request = new HttpPost(url);

		HttpResponse response;
		JSONObject loginAnswer = new JSONObject();

		// Add JSON object to the HTTP request.
		request.setEntity(new ByteArrayEntity(json.toString().getBytes("UTF8")));

		try {
			response = client.execute(request);
			HttpEntity entity = response.getEntity();

			if (entity != null) {
				// A Simple JSON Response Read
				InputStream instream = entity.getContent();
				String result = convertStreamToString(instream);

				loginAnswer = new JSONObject(result);

				instream.close();
			}

			responseJSON = loginAnswer.getInt("credentialLevel");
			Menu.key = loginAnswer.getString("key");

		} catch (Exception e) {
			// TODO
		}

		return responseJSON;
	}
	
	/**
	 * Method to force the server to close the session of the user when we exit
	 * this application (security matter).
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public void destroySession() throws ClientProtocolException, IOException{

		// Create new connection.
		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
		HttpConnectionParams.setSoTimeout(httpParams, 10000);
		HttpClient client = new DefaultHttpClient(httpParams);

		// Define request in right method.
		String url = Menu.RESTURIAddRecord;

		HttpDelete request = new HttpDelete(url);

		// Add JSON object to the HTTP request.
		request.setHeader("Cookie", "JSESSIONID=" + Menu.key);

		// Execute request.
		client.execute(request);
	}

	/**
	 * Method to send a JSON object and get server response.
	 * @param array
	 * @return the JSON response
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public String sendRecord(JSONArray array) throws ClientProtocolException, IOException{

		// Variables.
		String responseJSON = "";

		// Create new connection.
		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
		HttpConnectionParams.setSoTimeout(httpParams, 10000);
		HttpClient client = new DefaultHttpClient(httpParams);

		// Define request in right method.
		String url = Menu.RESTURIAddRecord;

		HttpPost request = new HttpPost(url);

		// Add JSON object to the HTTP request.
		request.setHeader("Cookie", "JSESSIONID=" + Menu.key);
		request.setEntity(new ByteArrayEntity(array.toString().getBytes("UTF8")));

		// Execute request.
		responseHttp = client.execute(request);
		responseCode = responseHttp.getStatusLine().getStatusCode();

		return responseJSON;
	}

	/**
	 * Method to convert an inputStream to a String.
	 * @param is
	 * @return the string yield from an InputStream.
	 */
	private static String convertStreamToString(InputStream is) {

		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;

		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}

	// ---------------------------------------------------------------
	// Getters - setters.
	// ---------------------------------------------------------------
	
	/**
	 * Getter to get the response of the service.
	 * @return the response of the service as Integer.
	 */
	public String getResponse() {
		return response;
	}

	/**
	 * Getter to get the error message in case of troubles like timeout or else.
	 * @return the error message as String.
	 */
	public String getErrorMessage() {
		return message;
	}

	/**
	 * Getter to get the response code of the request.
	 * @return the response code of the request.
	 */
	public int getResponseCode() {
		return responseCode;
	}
}